package view;
import io.ExportXML;
import io.FileSaveDialog;import io.ImageReader;
import java.awt.*;
import java.awt.event.*;
import java.io.File;import javax.swing.*;
import model.Prescription;
/**
 * The designer interface for the user to work with.
 * @author Daniel Bond, Mohammed Abdullah, Gideon Pyzer, Marvin Crawford
 *
 */
@SuppressWarnings("serial")
public class Designer extends JFrame {
	private int selectedObjectIndex;
	private JDesktopPane desktop;
	private JInternalFrame editorFrame;
	private Canvas canvas;
	private Toolbox toolbox;
	private TemplateList templateList;
	private IOPanel ioPanel;
	private Prescription prescription;
	private static Designer instance;
	private Designer()
	{
		super("Prescription Designer");
		this.setJMenuBar(new DesignerMenu());
		prescription = Prescription.getInstance();
		canvas = Canvas.getInstance();
		toolbox = Toolbox.getInstance();
		selectedObjectIndex = 0;

	}
	/**
	 * Get instance of designer (singleton)
	 * @return instance
	 */
	public static Designer getInstance()
	{
		if (instance == null)
		{
			instance = new Designer();
		}
		return instance;
	}
	/**
	 * Draw the GUI
	 */
	public void drawGUI()
	{
		drawEditorFrame();
		drawDesktopPane();
		ioPanel = new IOPanel();
		this.add(new ImageReader().readImage(), BorderLayout.NORTH);
		templateList = new TemplateList();
		this.add(templateList.getFilteredFiles(), BorderLayout.WEST);
		this.add(ioPanel, BorderLayout.SOUTH);
		ioPanel.setGreyed();
		this.add(ioPanel, BorderLayout.SOUTH);
		addNewPrescription();
		this.pack();
		this.setExtendedState(Frame.MAXIMIZED_BOTH);	// maximise the screen
		this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
		this.addWindowListener(new WindowAdapter()
		{
			public void windowClosing(WindowEvent e)
			{
				exitApp();
			}
		});
		this.setVisible(true);
	}
	/**
	 * Get the currently selected object index
	 * @return the currently selected item
	 */
	public int getObjectIndex()
	{
		return selectedObjectIndex;
	}
	/**
	 * Creates a new empty prescription
	 */
	private void addNewPrescription()
	{
		prescription.clear();	// clear any existing prescription
		prescription = Prescription.getInstance();	// create a new instance
		this.update();
		canvas.repaint();
	}
	/**
	 * Draw the editor frame which houses the prescription canvas
	 */
	private void drawEditorFrame()
	{
		editorFrame = new JInternalFrame(prescription.getName() + " - " + prescription.getSerialNo(), false, false, false, false); 
		editorFrame.setPreferredSize(new Dimension(prescription.getWidth()+7, prescription.getHeight()+30));
		editorFrame.add(canvas, BorderLayout.CENTER);
		editorFrame.setLocation(200, 20);
		editorFrame.setVisible(true);	
	}
	/**
	 * Draw the desktop pane which surrounds the editor frame
	 */
	private void drawDesktopPane() 
	{
		desktop = new JDesktopPane();
		desktop.add(editorFrame); 
		// sets editor to expand to desktop pane
		/*
		try {
			editorFrame.setMaximum(true);
		} catch (PropertyVetoException e) {
			e.printStackTrace();
		}
		 */
		this.add(desktop);
	}
	/**
	 * Update the GUI after prescription has changed
	 */
	public void update()
	{
		Prescription prescription = Prescription.getInstance();
		editorFrame.setSize(prescription.getWidth()+7, prescription.getHeight()+30);
		editorFrame.repaint();
		updateTitle();
		toolbox.update(selectedObjectIndex);
		this.repaint();
	}	/**	 * Updates the title of the currently open prescription	 */
	public void updateTitle()
	{
		Prescription prescription = Prescription.getInstance();
		String title = prescription.getName() + " - " + prescription.getSerialNo();
		if (prescription.hasChanged())
		{
			editorFrame.setTitle(title + "*");
		}
		else
		{
			editorFrame.setTitle(title);
		}
		this.repaint();
	}
	/**
	 * Set the currently selected index
	 * @param index the index to set as the currently selected object
	 */
	public void setSelectedIndex(int index)
	{
		selectedObjectIndex = index;
	}
	/**
	 * Exit the application with option to save changes
	 */
	public void exitApp()
	{		int result = showConfirmDialog("Are you sure you want to exit the application?",				"Exit Application",				JOptionPane.YES_NO_OPTION);
		if (result == JOptionPane.YES_OPTION)	//Only exit application if user chooses Yes
		{
			saveChanges(true);
		}
		else
		{
			return;
		}            
	}
	/**
	 * Save prescription changes	 * @param exit true if the user wants to exit the program
	 */
	public boolean saveChanges(boolean exit)
	{
		prescription = Prescription.getInstance();
		if (prescription.hasChanged())
		{			int resultSave = showConfirmDialog("Do you want to save any changes?",					"Save Changes",					JOptionPane.YES_NO_CANCEL_OPTION);

			if(resultSave == JOptionPane.YES_OPTION)
			{				FileSaveDialog fsd = FileSaveDialog.getInstance();				File selected = fsd.show();				if(selected != null){					String filename = selected.getPath();					ExportXML.export(filename);					Prescription.getInstance().setUnchanged();				}
				// export changes and exit

				if (exit == true){					System.exit(0); 				}
			}
			else if (resultSave == JOptionPane.CANCEL_OPTION)
			{
				return false;
			}
		}
		// discard the changes and exit application
		if (exit == true) { System.exit(0); }
		return true;
	}

	/**
	 * swaps the template list and tool box around
	 * @param change false if toolbox should not be switched
	 */
	public void switchLists(boolean change)
	{
		for (Component c : this.getContentPane().getComponents())
		{
			if (c instanceof JList)
			{
				this.remove(templateList);
				this.validate();
				this.add(toolbox, BorderLayout.WEST);
				ioPanel.setUsable();
			}
			if (c instanceof Toolbox)
			{
				if (!change) { return; }
				this.remove(toolbox);
				this.validate();
				this.add(templateList.getFilteredFiles(), BorderLayout.WEST);
				ioPanel.setGreyed();
			}
		}
		this.validate();
	}
	/**
	 * Set coordinates in ioPanel
	 * @param text the set of coordinates to be displayed
	 */
	public void setCoords(String text){
		ioPanel.setCoords(text);
	}
	/**
	 * get the IO Panel
	 * @return the IOPanel object
	 */
	public IOPanel getIOPanel(){
		return ioPanel;
	}
	/**
	 * set the IO panel buttons to usable
	 */
	public void setButtonsUsable(){
		ioPanel.setUsable();
	}	/**	 * Utility function to allow the program to show a dialog box to the user	 * @param text the text to display to the user	 */	public void showMessageDialog(String text){		JOptionPane.showMessageDialog(this, text);	}	/**	 * Utility function to display a dialog box prompt to the user	 * @param s the message to be displayed to the user	 * @param t the title of the dialog box	 * @param n the message type to display. Is typically a class constant from the class {@link javax.swing.JOptionPane}	 */	public void showMessageDialog(String s, String t, int n){		JOptionPane.showMessageDialog(this, s, t, n);	}	/**	 * Utility function to display a confirmation dialog box to the user	 * @param s the message to be displayed to the user	 * @param t the title of the dialog box	 * @param n the message type to display. Is typically a class constant from the class {@link javax.swing.JOptionPane}	 * @return an integer depending on the selection by the user	 */	public int showConfirmDialog(String s, String t, int n){		return JOptionPane.showConfirmDialog(this, s, t, n);	}
}
